//
//  UIViewExtension.swift
//  ezyform
//
//  Created by MoennigQ on 16/02/2017.
//  Copyright © 2017 Client.Solution Pty Ltd. All rights reserved.
//

import UIKit
import MBProgressHUD
import WebKit
extension UIView {
    func rotate360Degrees(duration: CFTimeInterval = 1.0) {
        let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
        rotateAnimation.fromValue = 0.0
        rotateAnimation.toValue = CGFloat(Double.pi * 2.0)
        rotateAnimation.duration = duration
        
        self.layer.add(rotateAnimation, forKey: nil)
    }
    //MARK:- 绘制虚线
    func drawDottedLine(start p0: CGPoint, end p1: CGPoint, color: UIColor) {
        let shapeLayer = CAShapeLayer()
        shapeLayer.strokeColor = color.cgColor
        shapeLayer.lineWidth = 1
        shapeLayer.lineDashPattern = [7, 3] // 7 is the length of dash, 3 is length of the gap.
        
        let path = CGMutablePath()
        path.addLines(between: [p0, p1])
        shapeLayer.path = path
        self.layer.addSublayer(shapeLayer)
    }
    //MARK:-add shadow
    func addShadowView(width:CGFloat=0.2, height:CGFloat=0.2, Opacidade:Float=0.7, maskToBounds:Bool=false, radius:CGFloat=0.5){
        self.layer.shadowColor = UIColor.black.cgColor
        self.layer.shadowOffset = CGSize(width: width, height: height)
        self.layer.shadowRadius = radius
        self.layer.shadowOpacity = Opacidade
        self.layer.masksToBounds = maskToBounds
    }
    //MARK:-指定UIview的某些角为圆角
    func setMutiBorderRoundingCorners(_ rect: CGRect, _ corner:CGFloat) {
        
        let maskPath = UIBezierPath.init(roundedRect: rect,
                                         
                                         byRoundingCorners: [UIRectCorner.topLeft, UIRectCorner.topRight],
                                         
                                         cornerRadii: CGSize(width: corner, height: corner))
        
        let maskLayer = CAShapeLayer()
        
        maskLayer.frame = self.bounds
        
        maskLayer.path = maskPath.cgPath
        
        self.layer.mask = maskLayer
    }
}

extension UITableView {
    
    /*
     弹出一个静态的cell，无须注册重用，例如:
     let cell: GrayLineTableViewCell = tableView.mm_dequeueStaticCell(indexPath)
     即可返回一个类型为GrayLineTableViewCell的对象
     
     - parameter indexPath: cell对应的indexPath
     - returns: 该indexPath对应的cell
     */
    func mm_dequeueStaticCell<T: UITableViewCell>(indexPath: IndexPath) -> T {
        let reuseIdentifier = "staticCellReuseIdentifier - \(indexPath.description)"
        if let cell = self.dequeueReusableCell(withIdentifier: reuseIdentifier) as? T {
            return cell
        }else {
            let cell = T(style: .default, reuseIdentifier: reuseIdentifier)
            return cell
        }
    }
}
public enum Model : String {
    case simulator   = "simulator/sandbox",
    iPod1            = "iPod 1",
    iPod2            = "iPod 2",
    iPod3            = "iPod 3",
    iPod4            = "iPod 4",
    iPod5            = "iPod Touch 5",
    iPod6            = "iPod Touch 6",
    iPad2            = "iPad 2",
    iPad3            = "iPad 3",
    iPad4            = "iPad 4",
    iPhone4          = "iPhone 4",
    iPhone4S         = "iPhone 4S",
    iPhone5          = "iPhone 5",
    iPhone5S         = "iPhone 5S",
    iPhone5C         = "iPhone 5C",
    iPadMini1        = "iPad Mini 1",
    iPadMini2        = "iPad Mini 2",
    iPadMini3        = "iPad Mini 3",
    iPadAir1         = "iPad Air 1",
    iPadAir2         = "iPad Air 2",
    iPadPro9_7       = "iPad Pro 9.7",
    iPadPro9_7_cell  = "iPad Pro 9.7 cellular",
    iPadPro10_5      = "iPad Pro 10.5",
    iPadPro10_5_cell = "iPad Pro 10.5 cellular",
    iPadPro12_9      = "iPad Pro 12.9",
    iPadPro12_9_cell = "iPad Pro 12.9 cellular",
    iPhone6          = "iPhone 6",
    iPhone6plus      = "iPhone 6 Plus",
    iPhone6S         = "iPhone 6S",
    iPhone6Splus     = "iPhone 6S Plus",
    iPhoneSE         = "iPhone SE",
    iPhone7_CDMA          = "iPhone 7 (CDMA)",
    iPhone7plus_CDMA      = "iPhone 7 Plus (CDMA)",
    iPhone7_GSM         = "iPhone 7 (GSM)",
    iPhone7plus_GSM      = "iPhone 7 Plus (GSM)",
    iPhone8          = "iPhone 8",
    iPhone8plus      = "iPhone 8 Plus",
    iPhoneX          = "iPhone X",
    iPhoneXS         = "iPhone XS",
    iPhoneXSMax      = "iPhone XS Max",
    iPhoneXR         = "iPhone XR",
    iPhone11         = "iPhone 11",
    iPhone11Pro         = "iPhone 11 Pro",
    iPhone11ProMax         = "iPhone 11 Pro Max",
    unrecognized     = "?unrecognized?"
}
extension UIDevice {
    static let isSimulator: Bool = {
        var isSim = false
        #if targetEnvironment(simulator)
            isSim = true
        #endif
        return isSim
    }()
    var modelName: String {
        var systemInfo = utsname()
        uname(&systemInfo)
        let machineMirror = Mirror(reflecting: systemInfo.machine)
        let modelCode = machineMirror.children.reduce("") { identifier, element in
            guard let value = element.value as? Int8, value != 0 else { return identifier }
            return identifier + String(UnicodeScalar(UInt8(value)))
        }
        
        let modelMap : [ String : Model ] = [
            "i386"       : .simulator,
            "x86_64"     : .simulator,
            "iPod1,1"    : .iPod1,
            "iPod2,1"    : .iPod2,
            "iPod3,1"    : .iPod3,
            "iPod4,1"    : .iPod4,
            "iPod5,1"    : .iPod5,
            "iPod7,1"    : .iPod6,
            "iPad2,1"    : .iPad2,
            "iPad2,2"    : .iPad2,
            "iPad2,3"    : .iPad2,
            "iPad2,4"    : .iPad2,
            "iPad2,5"    : .iPadMini1,
            "iPad2,6"    : .iPadMini1,
            "iPad2,7"    : .iPadMini1,
            "iPhone3,1"  : .iPhone4,
            "iPhone3,2"  : .iPhone4,
            "iPhone3,3"  : .iPhone4,
            "iPhone4,1"  : .iPhone4S,
            "iPhone5,1"  : .iPhone5,
            "iPhone5,2"  : .iPhone5,
            "iPhone5,3"  : .iPhone5C,
            "iPhone5,4"  : .iPhone5C,
            "iPad3,1"    : .iPad3,
            "iPad3,2"    : .iPad3,
            "iPad3,3"    : .iPad3,
            "iPad3,4"    : .iPad4,
            "iPad3,5"    : .iPad4,
            "iPad3,6"    : .iPad4,
            "iPhone6,1"  : .iPhone5S,
            "iPhone6,2"  : .iPhone5S,
            "iPad4,1"    : .iPadAir1,
            "iPad4,2"    : .iPadAir2,
            "iPad4,4"    : .iPadMini2,
            "iPad4,5"    : .iPadMini2,
            "iPad4,6"    : .iPadMini2,
            "iPad4,7"    : .iPadMini3,
            "iPad4,8"    : .iPadMini3,
            "iPad4,9"    : .iPadMini3,
            "iPad6,3"    : .iPadPro9_7,
            "iPad6,11"   : .iPadPro9_7,
            "iPad6,4"    : .iPadPro9_7_cell,
            "iPad6,12"   : .iPadPro9_7_cell,
            "iPad6,7"    : .iPadPro12_9,
            "iPad6,8"    : .iPadPro12_9_cell,
            "iPad7,3"    : .iPadPro10_5,
            "iPad7,4"    : .iPadPro10_5_cell,
            "iPhone7,1"  : .iPhone6plus,
            "iPhone7,2"  : .iPhone6,
            "iPhone8,1"  : .iPhone6S,
            "iPhone8,2"  : .iPhone6Splus,
            "iPhone8,4"  : .iPhoneSE,
            "iPhone9,1"  : .iPhone7_CDMA,
            "iPhone9,2"  : .iPhone7plus_CDMA,
            "iPhone9,3"  : .iPhone7_GSM,
            "iPhone9,4"  : .iPhone7plus_GSM,
            "iPhone10,1" : .iPhone8,
            "iPhone10,2" : .iPhone8plus,
            "iPhone10,3" : .iPhoneX,
            "iPhone10,4" : .iPhone8,
            "iPhone10,5" : .iPhone8plus,
            "iPhone10,6" : .iPhoneX,
            "iPhone11,2" : .iPhoneXS,
            "iPhone11,4" : .iPhoneXSMax,
            "iPhone11,6" : .iPhoneXSMax,
            "iPhone11,8" : .iPhoneXR,
            "iPhone12,1" : .iPhone11,
            "iPhone12,3" : .iPhone11Pro,
            "iPhone12,5" : .iPhone11Pro,
        ]
        
        if let model = modelMap["\(modelCode)"] {
            return model.rawValue
        }
        return modelCode
    }
    //MARK: - 获取设备类型
    static func getCurrentDeviceType() -> String{
        let currentDeviceModel = UIDevice.current.model as NSString
        var currentDevice : String!
        if currentDeviceModel.contains(APPConfig.iPadType) {//iPad Portrait
            currentDevice = APPConfig.iPadType
        }else {//iPhone Portrait
            currentDevice = APPConfig.iPhoneType
        }
        return currentDevice
        
    }
    //MARK: - 获取底部安全区域的高度
    static func getTopAreaHeight()->CGFloat{
        if #available(iOS 13.0, *) {
            let scene = UIApplication.shared.connectedScenes.first
            guard let windowScene = scene as? UIWindowScene else { return 0 }
            guard let window = windowScene.windows.first else { return 0 }
            return window.safeAreaInsets.top
        } else  {
            guard let window = UIApplication.shared.windows.first else { return 0 }
            return window.safeAreaInsets.top
        }
        
    }
    //MARK: - 获取底部安全区域的高度
    static func getBottomAreaHeight()->CGFloat{
        if #available(iOS 13.0, *) {
            let scene = UIApplication.shared.connectedScenes.first
            guard let windowScene = scene as? UIWindowScene else { return 0 }
            guard let window = windowScene.windows.first else { return 0 }
            return window.safeAreaInsets.bottom
        } else  {
            guard let window = UIApplication.shared.windows.first else { return 0 }
            return window.safeAreaInsets.bottom
        }
        
    }
    //MARK: - 获取status bar 高度
    static func getStatusBarHeight()->CGFloat{
        var statusBarHeight: CGFloat = 0
        if #available(iOS 13.0, *) {
            let scene = UIApplication.shared.connectedScenes.first
            guard let windowScene = scene as? UIWindowScene else { return 0 }
            guard let statusBarManager = windowScene.statusBarManager else { return 0 }
            statusBarHeight = statusBarManager.statusBarFrame.height
        } else {
            statusBarHeight = UIApplication.shared.statusBarFrame.height
        }
        return statusBarHeight
    }
    static func getTabbarHeight()->CGFloat{
        return 49
    }
    //get height of status bar and navigation bar
    public func getStatusBarAndNaviBarHeight() -> CGFloat {
        var height: CGFloat = 0
        let statusBarHeight = UIDevice.getStatusBarHeight()
        if UIDevice.current.userInterfaceIdiom == .pad {//ipad
            height = statusBarHeight + 50//height of iPad navi bar is 50
        }else{//iphone
            height = statusBarHeight + 44//height of iPhone navi bar is 44
        }
        
        return height
        
    }
    
}
extension UITextView {
    
    fileprivate struct RuntimeKey {
        static let placeholder = UnsafeRawPointer.init(bitPattern: "PLACEHOLDEL".hashValue)
        static let limitLength = UnsafeRawPointer.init(bitPattern: "LIMITLENGTH".hashValue)
        static let limitLines = UnsafeRawPointer.init(bitPattern: "LIMITLINES".hashValue)
        static let placeholderLabel = UnsafeRawPointer.init(bitPattern: "PLACEHOLDELABEL".hashValue)
        static let wordCountLabel = UnsafeRawPointer.init(bitPattern: "WORDCOUNTLABEL".hashValue)
        static let placeholdFont = UnsafeRawPointer.init(bitPattern: "PLACEHOLDFONT".hashValue)
        static let placeholdColor = UnsafeRawPointer.init(bitPattern: "PLACEHOLDCOLOR".hashValue)
        static let limitLabelFont = UnsafeRawPointer.init(bitPattern: "LIMITLABELFONT".hashValue)
        static let limitLabelColor = UnsafeRawPointer.init(bitPattern: "LIMITLABLECOLOR".hashValue)
        static let autoHeight = UnsafeRawPointer.init(bitPattern: "AUTOHEIGHT".hashValue)
        static let oldFrame = UnsafeRawPointer.init(bitPattern: "LODFRAME".hashValue)
        
        // ...其他Key声明
    }
    /*
     *  使用runtime添加属性
     */
    var placeholder: String? {//占位符
        set {
            objc_setAssociatedObject(self, UITextView.RuntimeKey.placeholder!, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
            initPlaceholder(placeholder!)
        }
        get {
            return  objc_getAssociatedObject(self, UITextView.RuntimeKey.placeholder!) as? String
        }
    }
    var limitLength: NSNumber? {//限制的字数
        set {
            objc_setAssociatedObject(self, UITextView.RuntimeKey.limitLength!, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
            initWordCountLabel(limitLength!)
        }
        get {
            return  objc_getAssociatedObject(self, UITextView.RuntimeKey.limitLength!) as? NSNumber
        }
    }
    var limitLines: NSNumber? {//限制的行数
        set {
            objc_setAssociatedObject(self, UITextView.RuntimeKey.limitLines!, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
            NotificationCenter.default.addObserver(self, selector: #selector(limitLengthEvent), name: UITextView.textDidChangeNotification, object: self)
        }
        get {
            return  objc_getAssociatedObject(self, UITextView.RuntimeKey.limitLines!) as? NSNumber
        }
    }
    var placeholderLabel: BaseLabel? {
        set {
            objc_setAssociatedObject(self, UITextView.RuntimeKey.placeholderLabel!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get {
            return  objc_getAssociatedObject(self, UITextView.RuntimeKey.placeholderLabel!) as? BaseLabel
        }
    }
    var wordCountLabel: BaseLabel? {
        set {
            objc_setAssociatedObject(self, UITextView.RuntimeKey.wordCountLabel!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get {
            return  objc_getAssociatedObject(self, UITextView.RuntimeKey.wordCountLabel!) as? BaseLabel
        }
    }
    
    var placeholdFont: UIFont? {
        set {
            objc_setAssociatedObject(self, UITextView.RuntimeKey.placeholdFont!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            if self.placeholderLabel != nil {
                self.placeholderLabel?.font = placeholdFont
            }
        }
        get {
            return  objc_getAssociatedObject(self, UITextView.RuntimeKey.placeholdFont!) as? UIFont == nil ? UIFont.systemFont(ofSize: 13) : objc_getAssociatedObject(self, UITextView.RuntimeKey.placeholdFont!) as? UIFont
        }
    }
    
    var limitLabelFont: UIFont? {
        set {
            objc_setAssociatedObject(self, UITextView.RuntimeKey.limitLabelFont!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            if self.wordCountLabel != nil {
                self.wordCountLabel?.font = limitLabelFont
            }
        }
        get {
            return  objc_getAssociatedObject(self, UITextView.RuntimeKey.limitLabelFont!) as? UIFont == nil ? UIFont.systemFont(ofSize: 13) : objc_getAssociatedObject(self, UITextView.RuntimeKey.limitLabelFont!) as? UIFont
        }
    }
    var placeholdColor: UIColor? {
        set {
            objc_setAssociatedObject(self, UITextView.RuntimeKey.placeholdColor!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            if self.placeholderLabel != nil {
                self.placeholderLabel?.textColor = placeholdColor
            }
        }
        get {
            return  objc_getAssociatedObject(self, UITextView.RuntimeKey.placeholdColor!) as? UIColor == nil ? UIColor.lightGray : objc_getAssociatedObject(self, UITextView.RuntimeKey.placeholdColor!) as? UIColor
        }
    }
    var limitLabelColor: UIColor? {
        set {
            objc_setAssociatedObject(self, UITextView.RuntimeKey.limitLabelColor!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            if self.wordCountLabel != nil {
                self.wordCountLabel?.textColor = limitLabelColor
            }
        }
        get {
            return  objc_getAssociatedObject(self, UITextView.RuntimeKey.limitLabelColor!) as? UIColor == nil ? UIColor.lightGray : objc_getAssociatedObject(self, UITextView.RuntimeKey.limitLabelColor!) as? UIColor
        }
    }
    var oldFrame: CGRect? {
        set {
            objc_setAssociatedObject(self, UITextView.RuntimeKey.oldFrame!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get {
            return  objc_getAssociatedObject(self, UITextView.RuntimeKey.oldFrame!) as? CGRect
        }
    }
    var autoHeight: Bool? {
        set {
            objc_setAssociatedObject(self, UITextView.RuntimeKey.autoHeight!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get {
            return  objc_getAssociatedObject(self, UITextView.RuntimeKey.autoHeight!) as? Bool
        }
    }
    /*
     *  占位符
     */
    fileprivate func initPlaceholder(_ placeholder: String) {
        
        NotificationCenter.default.addObserver(self, selector: #selector(textChange(_:)), name: UITextView.textDidChangeNotification, object: self)
        NotificationCenter.default.addObserver(self, selector: #selector(textBeginEditing(_:)), name: UITextView.textDidBeginEditingNotification, object: self)
        NotificationCenter.default.addObserver(self, selector: #selector(textEndEditing(_:)), name: UITextView.textDidEndEditingNotification, object: self)
        self.placeholderLabel = BaseLabel()
        placeholderLabel?.setFont(self.placeholdFont)
        placeholderLabel?.text = placeholder
        placeholderLabel?.numberOfLines = 0
        placeholderLabel?.lineBreakMode = .byWordWrapping
        placeholderLabel?.textColor = self.placeholdColor
        
        let rect = placeholder.boundingRect(with: CGSize(width: APPConfig.WidthForPortrait - 27 * 2, height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font : self.placeholderLabel!.font!], context: nil)
//        if rect.size.height > 30 {
//            placeholderLabel?.frame = CGRect(x: 7, y: 7, width: APPConfig.WidthForPortrait - 27 * 2, height: 40)
//        }else{
            placeholderLabel?.frame = CGRect(x: 7, y: 7, width: APPConfig.WidthForPortrait - 27 * 2, height: rect.size.height)
//        }

        addSubview(self.placeholderLabel!)
        placeholderLabel?.isHidden = self.text.count > 0 ? true : false
    }
    
    /*
     *  字数限制
     */
    fileprivate func initWordCountLabel(_ limitLength : NSNumber) {
        
        NotificationCenter.default.addObserver(self, selector: #selector(limitLengthEvent), name: UITextView.textDidChangeNotification, object: self)
        if wordCountLabel != nil {
            wordCountLabel?.removeFromSuperview()
        }
        wordCountLabel = BaseLabel(frame: CGRect(x: 0, y: self.frame.size.height - 20, width: self.frame.size.width - 10, height: 20))
        wordCountLabel?.textAlignment = .right
        wordCountLabel?.textColor = self.limitLabelColor
        wordCountLabel?.setFont(self.limitLabelFont)
        if self.text.count > limitLength.intValue {
            self.text = (self.text as NSString).substring(to: limitLength.intValue)
        }
        let inputLength = self.covertToInt(self.text! as NSString)
        wordCountLabel?.text = "\(inputLength)/\(limitLength)"
        addSubview(wordCountLabel!)
        self.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 20, right: 0)
        
    }
    //get length of  string with chinese and english
    private func covertToInt(_ strtemp: NSString) -> Int {
        let enc: String.Encoding = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(UInt32(CFStringEncodings.GB_18030_2000.rawValue)))
        let data: NSData = NSData(data: strtemp.data(using: enc.rawValue)!)
        
        return data.length
        
    }
    
    /*
     *  动态监听
     */
    @objc func textChange(_ notification : Notification) {
        
        if placeholder != nil {
            placeholderLabel?.isHidden = (self.text.count ==  0 ? false : true)
        }
        if limitLength != nil {
            var inputLength = self.covertToInt(self.text! as NSString)
            if inputLength > (limitLength?.intValue)! {
                inputLength = (limitLength?.intValue)!
                self.text = String(self.text!.prefix(limitLength!.intValue))
            }
            let limit = limitLength!.stringValue
            wordCountLabel?.text = "\(inputLength)/\(limit)"
        }
        if autoHeight == true && self.oldFrame != nil {
            let size = getStringPlaceSize(self.text, textFont: self.font!)
            UIView.animate(withDuration: 0.15) {
                self.frame = CGRect.init(x: (self.oldFrame?.origin.x)!, y: (self.oldFrame?.origin.y)!, width: (self.oldFrame?.size.width)!, height: size.height + 25 <= (self.oldFrame?.size.height)! ? (self.oldFrame?.size.height)! : size.height + 25)
            }
        }
        
    }
    @objc func textBeginEditing(_ notification : Notification) {
        if placeholder != nil {
            placeholderLabel?.isHidden = (self.text.count ==  0 ? false : true)
        }
    }
    @objc func textEndEditing(_ notification : Notification) {
        if placeholder != nil {
            placeholderLabel?.isHidden = (self.text.count ==  0 ? false : true)
        }
    }
    @objc fileprivate func limitLengthEvent() {
        if limitLength != nil {
            let inputLength = self.covertToInt(self.text! as NSString)
            if inputLength > (limitLength?.intValue)! && limitLength != nil {
                self.text = (self.text as NSString).substring(to: (limitLength?.intValue)!)
                print("Maximum number of words");
            }
        }else {
            if (limitLines != nil) {//行数限制
                let size = getStringPlaceSize(self.text, textFont: self.font!)
                let height = self.font!.lineHeight * CGFloat(limitLines!.floatValue)
                if (size.height > height) {
                    self.text = (self.text as NSString).substring(to: self.text.count - 1)
                    print("Maximum number of lines");
                }
            }
        }
    }
    
    @objc fileprivate func getStringPlaceSize(_ string : String, textFont : UIFont) -> CGSize {
        ///计算文本高度
        let attribute = [NSAttributedString.Key.font : textFont];
        let options = NSStringDrawingOptions.usesLineFragmentOrigin
        let size = string.boundingRect(with: CGSize(width: self.contentSize.width-10, height: CGFloat.greatestFiniteMagnitude), options: options, attributes: attribute, context: nil).size
        return size
    }
    override open func layoutSubviews() {
        super.layoutSubviews()
        if limitLength != nil && wordCountLabel != nil {
            /*
             *  避免外部使用了约束 这里再次更新frame
             */
            wordCountLabel!.frame = CGRect(x: 0, y: frame.height - 20 + contentOffset.y, width: frame.width - 10, height: 20)
        }
//        if placeholder != nil && placeholderLabel != nil {
//            let rect: CGRect = placeholder!.boundingRect(with: CGSize(width: frame.width - 7, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 13.0)], context: nil)
//            placeholderLabel!.frame = CGRect(x: 7, y: 7, width: rect.size.width, height: rect.size.height)
//        }
        if autoHeight == true {
            self.oldFrame = self.frame
            self.isScrollEnabled = false
        }else {
            self.isScrollEnabled = true
        }
    }
    
}

extension MBProgressHUD{
    class func showToast(parentView: UIView, text: String , delay: Double = 1.0, backColor: UIColor = .black, textColor: UIColor = .white){
        let hub = MBProgressHUD.showAdded(to: parentView, animated: true)
        //only display text
        hub?.mode = .text
        //background color
        hub?.color = backColor
//        hub?.minSize = CGSize(width: 200, height: 50)
        hub?.labelText = text
        hub?.labelColor = textColor
        hub?.hide(true, afterDelay: delay)
    }
    //白色背景
    class func showToastWithWhiteBg(parentView: UIView, text: String , delay: Double = 2.0){
            let hub = MBProgressHUD.showAdded(to: parentView, animated: true)
            //only display text
            hub?.mode = .text
            //background color
            hub?.color = .white
    //        hub?.minSize = CGSize(width: 200, height: 50)
            hub?.labelText = text
            hub?.labelColor = .black
            hub?.hide(true, afterDelay: delay)
        }
}
extension UITabBar {
    func showBadgeOnItem(index:Int, tabBarItemCnt: Int) {
        removeBadgeOnItem(index: index)
        let bview = UIView()
        bview.tag = 888+index
        bview.layer.cornerRadius = 5
        bview.clipsToBounds = true
        bview.backgroundColor = UIColor.red
        let tabFrame = self.frame
        
        let percentX = (Float(index)+0.6) / Float(tabBarItemCnt)
        let x = CGFloat(ceilf(percentX*Float(tabFrame.width)))
        let y = CGFloat(ceilf(0.1*Float(tabFrame.height)))
        bview.frame = CGRect(x: x, y: y, width: 10, height: 10)
        
//        let cLabel = UILabel.init()
//        cLabel.text = "\(count)"
//        cLabel.frame = CGRect(x: 0, y: 0, width: 10, height: 10)
//        cLabel.font = UIFont.systemFont(ofSize: 10)
//        cLabel.textColor = UIColor.white
//        cLabel.textAlignment = .center
//        bview.addSubview(cLabel)
        
        addSubview(bview)
        bringSubviewToFront(bview)
    }
    //隐藏红点
    func hideBadgeOnItem(index:Int) {
        removeBadgeOnItem(index: index)
    }
    //移除控件
    func removeBadgeOnItem(index:Int) {
        for subView:UIView in subviews {
            if subView.tag == 888+index {
                subView.removeFromSuperview()
            }
        }
    }
}
protocol ReusableView: AnyObject {
    static var reuseCellIdentifier: String { get }
}

extension ReusableView where Self: UIView {
    static var reuseCellIdentifier: String {
        return NSStringFromClass(self).components(separatedBy: ".").last!
    }
}
extension UICollectionViewCell: ReusableView {
}
extension UITableViewCell: ReusableView {
}
extension UIView{
    func drawCorner(byRoundingCorners corners: UIRectCorner, radii: CGFloat = 10, backColorHexStr: String = "#FFFFFFFF") {
        self.backgroundColor = UIColor(hexStr: backColorHexStr)
        var cornerMask = CACornerMask()
        //top left
        if corners.contains(UIRectCorner.topLeft){
            cornerMask.insert(CACornerMask.layerMinXMinYCorner)
        }
        //top right
        if corners.contains(UIRectCorner.topRight){
            cornerMask.insert(CACornerMask.layerMaxXMinYCorner)
        }
        //bottom left
        if corners.contains(UIRectCorner.bottomLeft){
            cornerMask.insert(CACornerMask.layerMinXMaxYCorner)
        }
        //bottom left
        if corners.contains(UIRectCorner.bottomRight){
            cornerMask.insert(CACornerMask.layerMaxXMaxYCorner)
        }
        self.layer.cornerRadius = radii
        self.layer.maskedCorners = cornerMask
        self.clipsToBounds = true
        
    }
    //MARK: 获取当前显示的导航控制器
    func firstNaviViewController() -> UINavigationController? {
        for view in sequence(first: self.superview, next: { $0?.superview }) {
            if let responder = view?.next {
                if responder.isKind(of: UINavigationController.self){
                    return responder as? UINavigationController
                }
            }
        }
        return nil
    }
    //MARK: - 画边框
    func drawBorder(backHexStr: String, borderHexStr: String, cornerRadius: CGFloat = Constant.StandardCornerRadius){
        self.backgroundColor = UIColor(hexStr: backHexStr)
        self.layer.borderColor = UIColor(hexStr: borderHexStr).cgColor
        self.layer.borderWidth = 1
        self.layer.cornerRadius = cornerRadius
        self.clipsToBounds = true
    }
    
}
extension UIColor {
    // Hex String -> UIColor
    convenience init(hexStr: String) {
        var hexString = hexStr.trimmingCharacters(in: .whitespacesAndNewlines)
        if hexString.count == 7 {
            hexString += "FF"
        }
        let scanner = Scanner(string: hexString)
        if hexString.hasPrefix("#") {
            scanner.scanLocation = 1
        }
        var color: UInt32 = 0
        scanner.scanHexInt32(&color)
        let mask = 0x0000FF
        let r = Int(color >> 24) & mask
        let g = Int(color >> 16) & mask
        let b = Int(color >> 8) & mask
        let a = Int(color) & mask
        let red   = CGFloat(r) / 255.0
        let green = CGFloat(g) / 255.0
        let blue  = CGFloat(b) / 255.0
        let alpha = CGFloat(a) / 255.0
        self.init(red: red, green: green, blue: blue, alpha: alpha)
    }
}
extension UIScrollView {

    // Scroll to a specific view so that it's top is at the top our scrollview
    func scrollToView(view:UIView, animated: Bool) {
        let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height)
        let viewFrameY = view.frame.origin.y
        if bottomOffset.y > 0{
            if viewFrameY > bottomOffset.y {//view的Y超过的最大的Offset，就直接滚动到底部即可
                setContentOffset(bottomOffset, animated: animated)
            }else{
                setContentOffset(view.frame.origin, animated: animated)
            }
        }
    }
    // Scroll to a specific view so that it's top is at the top our scrollview
    func scrollToView(point: CGPoint, animated: Bool) {
        let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height)
        let viewFrameY = point.y
        if bottomOffset.y > 0{
            if viewFrameY > bottomOffset.y {//view的Y超过的最大的Offset，就直接滚动到底部即可
                setContentOffset(bottomOffset, animated: animated)
            }else{
                setContentOffset(point, animated: animated)
            }
        }
    }
    // Bonus: Scroll to top
    func scrollToTop(animated: Bool) {
        let topOffset = CGPoint(x: 0, y: 0)
        setContentOffset(topOffset, animated: animated)
    }

    // Bonus: Scroll to bottom
    func scrollToBottom() {
        let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height)
        if(bottomOffset.y > 0) {
            setContentOffset(bottomOffset, animated: true)
        }
    }

}
extension UILabel {
    func setAppearenceColor(textColorHexWithAlpha: String? = nil, backColorHexWithAlpha: String? = nil, borderColorHexWithAlpha: String? = nil, cornerRadius: CGFloat? = nil ){
        if let hexStr =  textColorHexWithAlpha{
            self.textColor = UIColor(hexStr: hexStr)
        }
        if let hexStr =  backColorHexWithAlpha{
            self.backgroundColor = UIColor(hexStr: hexStr)
        }
        if let hexStr = borderColorHexWithAlpha, let radius = cornerRadius{
            self.layer.borderColor = UIColor(hexStr: hexStr).cgColor
            self.layer.borderWidth = 1
            self.layer.cornerRadius = radius
            self.clipsToBounds = true
        }
    }
}
extension String {
    //MARK: - 将json 字符串格式化后打印，方便查看
    func jsonFormatPrint() -> String {
     
        if (self.starts(with: "{") || self.starts(with: "[")){
            var level = 0
            var jsonFormatString = String()
            
            func getLevelStr(level:Int) -> String {
                var string = ""
                for _ in 0..<level {
                    string.append("\t")
                }
                return string
            }
            
            for char in self {
                
                if level > 0 && "\n" == jsonFormatString.last {
                    jsonFormatString.append(getLevelStr(level: level))
                }
                
                switch char {
                    
                case "{":
                    fallthrough
                case "[":
                    level += 1
                    jsonFormatString.append(char)
                    jsonFormatString.append("\n")
                case ",":
                    jsonFormatString.append(char)
                    jsonFormatString.append("\n")
                case "}":
                    fallthrough
                case "]":
                    level -= 1;
                    jsonFormatString.append("\n")
                    jsonFormatString.append(getLevelStr(level: level));
                    jsonFormatString.append(char);
                    break;
                default:
                    jsonFormatString.append(char)
                }
            }
            return jsonFormatString;
        }
        
        return self
    }
}
extension UIViewController {

    /// Adds child view controller to the parent.
    ///
    /// - Parameter child: Child view controller.
    func addChildVC(_ child: UIViewController) {
        addChild(child)
        child.view.frame = self.view.frame
        view.addSubview(child.view)
        // 通知子视图控制器已经被加入到父视图控制器中
        child.didMove(toParent: self)
    }

    //MARK: = It removes the child view controller from the parent.
    func removeChildVC() {
        guard parent != nil else {
            return
        }
        willMove(toParent: nil)
        removeFromParent()
        view.removeFromSuperview()
    }
    //MARK: -是否包含某个child controller
    func checkIfChildVCExist(_ child: UIViewController)->Bool{
        return self.children.contains(child)
    }
}
extension String {
    //
    func dateValue(format: String)->Date?{
        // 时间格式
        let formatter = DateFormatter()
        formatter.timeZone = TimeZone.init(abbreviation: "GMT")
        formatter.dateFormat = format
        return formatter.date(from: self)
    }
}
extension Date {
    private static var systemUptime: TimeInterval = 0
    private static var serverTime: TimeInterval = 0
    //APP操作过程中修改时间
    static func resetServerTime(){
        self.serverTime = 0
    }
    //MARK: - 同步网络时间，防止用户篡改时间
    static func sycn(){
        let url = URL(string: APPConfig.serverAddress)!
        let task = URLSession.shared.dataTask(with: url) { (data: Data?, resp: URLResponse?, err: Error?) in
            if let httpResp = resp as? HTTPURLResponse,
               let dateStr = httpResp.allHeaderFields["Date"] as? String {
                
                let serverDate: Date!
                if let date = dateStr.dateValue(format: "EEE, dd MMM yyyy HH:mm:ss zzzz"){
                    serverDate = date
                }else if let date = dateStr.dateValue(format: "EEE, dd MMM yyyy HH:mm:ss z") {
                    serverDate = date
                } else if let date = dateStr.dateValue(format: "EEE, d MMM yyyy HH:mm:ss z") {
                    serverDate = date
                    
                } else if let date = dateStr.dateValue(format: "dd MMM yyyy HH:mm:ss") {
                    serverDate = date
                } else if let date = dateStr.dateValue(format: "d MMM yyyy HH:mm:ss") {
                    serverDate = date
                    
                } else if let date = dateStr.dateValue(format: "dd MMM yyyy HH:mm") {
                    serverDate = date
                } else if let date = dateStr.dateValue(format: "d MMM yyyy HH:mm") {
                    serverDate = date
                } else {
                    return
                }
                
                // 互联网时间戳
                serverTime = serverDate.timeIntervalSince1970
                
                // 运行时间
                systemUptime = Double(now() - boottime())//processInfo.systemUptime
            }
        }
        task.resume()
    }
    //当前时间设备
    static func now() -> Int {
            var now =  timeval()
            var tz = timezone()
            gettimeofday(&now, &tz)
            return now.tv_sec
     }
    //设备启动的Second
    static func boottime() -> Int {
            var mid = [CTL_KERN, KERN_BOOTTIME]
            var boottime = timeval()
            var size = MemoryLayout.size(ofValue: boottime)

            if sysctl(&mid, 2, &boottime, &size, nil, 0) != -1 {
                return boottime.tv_sec
            }
            return 0
     }

    static var current: Date {
        if serverTime == 0 {
            if #available(iOS 15, *) {
                return Date.now
            } else {
                return Date()
            }
        } else {
            // 当前app运行时间 = (当前运行时间 - 旧运行时间)
            // 当前时间 = 旧服务器时间 + app运行时间
            // 当前时间 = 旧服务器时间 + (当前运行时间 - 旧运行时间)
            let nowTimeInterval = serverTime + (Double(now() - boottime()) - systemUptime)
            return Date(timeIntervalSince1970: nowTimeInterval)
        }
    }
}
